package com.itheima.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.itheima.common.R;
import com.itheima.dto.SetmealDto;
import com.itheima.pojo.Category;
import com.itheima.pojo.Setmeal;
import com.itheima.service.CategoryService;
import com.itheima.service.SetMealDishService;
import com.itheima.service.SetMealService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.web.bind.annotation.*;

import java.util.List;
import java.util.stream.Collectors;

// 套餐管理控制层
@Slf4j
@RestController
@RequestMapping("/setmeal")
@Api(tags = "套餐相关接口")
public class SetMealController {

    @Autowired
    private SetMealService setMealService;

    @Autowired
    private SetMealDishService setMealDishService;

    @Autowired
    private CategoryService categoryService;

    /*
    * value: 缓存的名称, 每个缓存名称下面可以有很多key
​	    key: 缓存的key  ----------> 支持Spring的表达式语言SPEL语法
    * */

    /*
    * 新增套餐(两步):
    * 1 根据分类对菜品信息进行查询:
    *       在DishController中定义list方法,查询信息
    * 2 保存套餐:
    *       1 在业务层SetMealService接口中定义新增套餐的方法
    *       2 在实现类中实现该方法并进行编辑
    *       3 在SetmealController中调用新增方法,并返回结果
    * */
    @PostMapping // 新增套餐
    @ApiOperation(value = "新增套餐的接口")
    @CacheEvict(value = "setmealGroup",allEntries = true) // 删除setmealCache名称下的所有缓存数据
    public R<String> save(@RequestBody SetmealDto setmealDto){
        log.info(" 套餐信息是:{}", setmealDto);

        // 调用新增方法进行查询
        setMealService.saveWithDish(setmealDto);

        // 返回结果
        return R.success("新增套餐成功");
    }

    // 套餐分页查询
    @GetMapping("/page")
    @ApiOperation(value = "套餐分页查询的接口")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "page",value = "页码",required = true),
            @ApiImplicitParam(name = "pageSize",value = "每页记录数",required = true),
            @ApiImplicitParam(name = "name",value = "套餐名称",required = false)
    })
    public R<Page> page(int page, int pageSize, String name){
        //1 创建分页构造器
        Page<Setmeal> setmealPage = new Page<>(page, pageSize);
        Page<SetmealDto> dtoPage = new Page<>();

        //2 创建条件构造器
        LambdaQueryWrapper<Setmeal> queryWrapper = new LambdaQueryWrapper<>();

        //3 添加查询条件 -> 通过"name"进行like模糊查询
        queryWrapper.like(name != null, Setmeal::getName,name);

        //4 添加排序条件 -> 按照信息更新时间进行降序排序
        queryWrapper.orderByDesc(Setmeal::getUpdateTime);

        //5 调用方法完成查询
        setMealService.page(setmealPage, queryWrapper);

        //6 遍历分页查询的列表数据 -> 根据分类id查询套餐分类名称 -> 获取套餐的基本信息及分类名称信息
        BeanUtils.copyProperties(setmealPage, dtoPage, "records");
        List<Setmeal> records = setmealPage.getRecords();
        List<SetmealDto> list = records.stream().map((item)->{
            //1 创建对象
            SetmealDto setmealDto = new SetmealDto();
            //2 对象拷贝
            BeanUtils.copyProperties(item, setmealDto);
            //3 套餐分类的id
            Long categoryId = item.getCategoryId();
            //4 根据分类的id查询对象的具体信息
            Category byId = categoryService.getById(categoryId);
            //5 对查询信息进行判断 -> 判断是否为空 -> 获取分类名称
            if (byId != null){
                String idName = byId.getName();//获取分类名称
                setmealDto.setCategoryName(idName);
            }
            return setmealDto;
        }).collect(Collectors.toList());

        //7 对获取到的信息进行封装并返回
        dtoPage.setRecords(list);
        return R.success(dtoPage);
    }

    // 删除套餐 -> 需先判定套餐的状态,若在售卖中,则不能删除
    //         ->删除套餐数据的同时,也应当删除与套餐相关联的菜品数据
    @DeleteMapping
    @CacheEvict(value = "setmealGroup",allEntries = true) // 删除setmealCache名称下的所有缓存数据
    @ApiOperation(value = "删除套餐的接口")
    public R<String> delete(@RequestParam List<Long> ids){
        log.info(" ids : {} ",ids);
        setMealService.removeSetMeal(ids);
        return R.success("删除成功");
    }

    // 根据分类id查询套餐信息
    @GetMapping("/list") // 在移动端进行菜品口味信息展示
    @Cacheable(value = "setmealGroup", key = "#setmeal.categoryId + '_' + #setmeal.status")
    @ApiOperation(value = "套餐条件查询接口")
    public R<List<Setmeal>> list(Setmeal setmeal){
        //1 创建条件构造器
        LambdaQueryWrapper<Setmeal> queryWrapper = new LambdaQueryWrapper<>();
        //2 添加查询条件  条件 : 套餐的数据不能为空
        queryWrapper.eq(setmeal.getCategoryId() != null, Setmeal::getCategoryId,setmeal.getCategoryId());
        queryWrapper.eq(setmeal.getStatus() != null, Setmeal::getStatus, setmeal.getStatus());
        //3 添加排序条件
        queryWrapper.orderByDesc(Setmeal::getUpdateTime);
        //4 调用方法完成查询
        List<Setmeal> list = setMealService.list(queryWrapper);
        //5 返回结果
        return R.success(list);
    }

    // 修改套餐 : -> 根据Id查询相对应的套餐菜品信息
    //          -> 修改套餐信息 -> 在setmealservice接口中添加方法
    //          -> 先更新套餐信息及相应的菜品信息 -> 清理当前套餐的菜品数据(setmeal_dish的删除操作)
    //          -> 再添加当前提交的菜品信息(setmeal_dish的添加操作) -> 最后在SetmealController中调用修改方法完成修改操作
    //1 根据id查询套餐对应的菜品信息
    @GetMapping("/{id}")
    @Cacheable(value = "setmealGroup", key = "#id", unless = "#result == null")
    @ApiOperation(value = "修改回显数据的接口")
    public R<SetmealDto> get(@PathVariable Long id){
        // 调用业务层实现类的方法完成套餐的菜品信息查询
        SetmealDto byIdDish = setMealService.getByIdDish(id);
        // 返回结果
        return R.success(byIdDish);
    }
    //2 修改套餐信息
    @PutMapping
    @CacheEvict(value = "setmealGroup",allEntries = true) // 删除setmealCache名称下的所有缓存数据
    @ApiOperation(value = "修改套餐信息的接口")
    public R<String> update(@RequestBody SetmealDto setmealDto){
        // 调用业务层实现类中的方法完成套餐的修改
        setMealService.updateDish(setmealDto);
        // 返回结果
        return R.success("修改套餐成功");
    }
}
